package com.geline.web.interceptor;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 重复提交拦截器，使用 hutool提供的TimedCache
 * 两次相同参数的请求，如果间隔时间大于该参数，系统不会认定为重复提交的数据
 * @author: mengx
 * @date: 2021/7/20 19:31
 */
@Slf4j
public class SameUrlCacheInterceptor extends RepeatSubmitInterceptor {
    public static final String REPEATPARAMS = "repeatParams";
    public static final String REPEATTIME = "repeatTime";
    //间隔时间，单位:秒 默认5秒
    private static final int intervalTime = 2;
    private static final TimedCache<String, Object> TimedCache = CacheUtil.newTimedCache(intervalTime*1000);

    public SameUrlCacheInterceptor(){
    }

    @Override
    public boolean isRepeatSubmit(HttpServletRequest request) {
        // 本次参数及系统时间
        String nowParams = JSONUtil.toJsonStr(request.getParameterMap());
        Map<String, Object> nowDataMap = new HashMap<>();
        nowDataMap.put(REPEATPARAMS, nowParams);
        nowDataMap.put(REPEATTIME, System.currentTimeMillis());

        // 请求地址（作为存放session的key值）
        String url = request.getRequestURI();
        Object cacheObj = TimedCache.get(url);
        if (cacheObj != null) {
            Map<String, Object> preDataMap = (Map<String, Object>) cacheObj;
            if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) {
                log.warn("RepeatSubmit nowDataMap = {}, preDataMap = {}", nowDataMap, preDataMap);
                return true;
            }
        }
        TimedCache.put(url, nowDataMap);
        return false;
    }

    /**
     * 判断参数是否相同
     */
    private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
        String nowParams = (String) nowMap.get(REPEATPARAMS);
        String preParams = (String) preMap.get(REPEATPARAMS);
        return nowParams.equals(preParams);
    }

    /**
     * 判断两次间隔时间
     */
    private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap) {
        long time1 = (Long) nowMap.get(REPEATTIME);
        long time2 = (Long) preMap.get(REPEATTIME);
        return (time1 - time2) < (intervalTime * 1000);
    }
}
